﻿using System;
using System.IO;

namespace Bangle.SerialPort.Utils
{
    public static class MemoryStreamExt
    {
        public static void Write(this MemoryStream ms, byte v)
        {
            ms.WriteByte(v);
        }

        public static void Write(this MemoryStream ms, byte[] buffer)
        {
            ms.Write(buffer, 0, buffer.Length);
        }

        public static void Write(this MemoryStream ms, UInt16 v)
        {
            ms.Write(UInt16ToBytes(v));
        }

        public static void Write(this MemoryStream ms, UInt32 v)
        {
            ms.Write(UInt32ToBytes(v));
        }

        public static void WriteCRC16(this MemoryStream ms)
        {
            var bytes = ms.ToArray();
            var crc = CRC16Helper.CRC16(bytes);
            ms.Write(crc[0]);
            ms.Write(crc[1]);
        }

        #region UInt16
        private static byte[] UInt16ToBytes(UInt16 val)
        {
            var res = new byte[2];
            res[0] = (byte)((val >> 8) & 0xFF);
            res[1] = (byte)(val & 0xFF);
            return res;
        }

        private static byte[] UInt16ToBytes(int val)
        {
            return UInt16ToBytes(Convert.ToUInt16(val));
        }

        private static byte[] Double16ToBytes(double val, double jd)
        {
            return UInt16ToBytes(Convert.ToUInt16(val * jd));
        }

        public static void WriteUInt16(this MemoryStream ms, int v)
        {
            ms.Write(UInt16ToBytes(v));
        }

        public static void WriteDouble16(this MemoryStream ms, double v, double jd)
        {
            ms.Write(Double16ToBytes(v, jd));
        }

        public static void WriteDouble16(this MemoryStream ms, double v, int jd)
        {
            var vv = Convert.ToUInt16(v * jd);
            ms.Write(vv);
        }
        #endregion

        #region UInt32
        private static byte[] UInt32ToBytes(UInt32 val)
        {
            var res = new byte[4];
            res[0] = (byte)((val >> 24) & 0xFF);
            res[1] = (byte)((val >> 16) & 0xFF);
            res[2] = (byte)((val >> 8) & 0xFF);
            res[3] = (byte)(val & 0xFF);
            return res;
        }

        private static byte[] Double32ToBytes(double val, double jd)
        {
            return UInt32ToBytes(Convert.ToUInt32(val * jd));
        }

        public static void WriteUInt32(this MemoryStream ms, long v)
        {
            ms.Write(UInt32ToBytes(Convert.ToUInt32(v)));
        }

        public static void WriteDouble32(this MemoryStream ms, double v, double jd)
        {
            ms.Write(Double32ToBytes(v, jd));
        }
        #endregion
    }
}
